/*
 * lector.cpp
 *
 *  Created on: Oct 30, 2013
 *      Author: m
 */

#include <iostream>
#include <cstdlib>
#include <ctime>
#include "DefinicionesComunes.h"
#include "NewMessageQueue.h"
#include "NewSemaphore.h"
#include "NewSharedMemory.h"
#include "Sequence.h"
#include "CPrinter.h"

using namespace ipc;

int main ( int argc, char* argv[] )
{
    int nLectores;
    int nLectoresConsecutivos;
    float valorDolar;
    int id;

    srand( time( NULL ) );

    id = Sequence::get( IPC_BASE_FILE, SEQ_ID_LECTOR ).getNext();

    CPrinter::setHeader( "lector", id );

    // IPCs
    SharedMemory<float> shmPrecioDolar =
            SharedMemory<float>::get( IPC_BASE_FILE, SHM_BOARD );
    SharedMemory<int> shmContadorLectores =
            SharedMemory<int>::get( IPC_BASE_FILE, SHM_CONT_LECT );
    SharedMemory<int> shmContadorLectoresConsecutivos =
                SharedMemory<int>::get( IPC_BASE_FILE, SHM_CONT_LCON );
    Semaphore semEscritor =
            Semaphore::get( IPC_BASE_FILE, SEM_ESCRITOR );
    Semaphore mutexContadorLectores =
            Semaphore::get( IPC_BASE_FILE, SEM_CONT_LECT );
    Semaphore semEntrada =
            Semaphore::get( IPC_BASE_FILE, SEM_ENTRADA );


    CPrinter::printOut( "INICIADO" );

    Semaphore::get( IPC_BASE_FILE, SEM_INICIO ).p();

    while ( true )
    {
        sleep( random() % 10 );

        semEntrada.p();

        mutexContadorLectores.p();

        nLectores = shmContadorLectores.read();
        nLectores++;
        shmContadorLectores.write( nLectores );

        if ( nLectores == 1 )
        {
            semEscritor.p();
        }

        nLectoresConsecutivos = shmContadorLectoresConsecutivos.read();
        nLectoresConsecutivos++;
        shmContadorLectoresConsecutivos.write( nLectoresConsecutivos );

        if ( nLectoresConsecutivos < MAX_LECTORES_CONSECUTIVOS )
        {
            semEntrada.v();
        }
        else
        {
            CPrinter::printOut( "Se alcanzo la cantidad maxima de lectores"
                    " consecutivos. Ya no se permite el ingreso de nuevos"
                    " lectores." );
        }

        mutexContadorLectores.v();

        sleep( random() % 10 );

        valorDolar = shmPrecioDolar.read();

        CPrinter::printOut( "Valor del dolar: $%.2f", valorDolar );

        mutexContadorLectores.p();

        nLectores = shmContadorLectores.read();
        nLectores--;
        shmContadorLectores.write( nLectores );

        if ( nLectores == 0 )
        {
            CPrinter::printOut( "Ultimo lector" );

            semEscritor.v();

            nLectoresConsecutivos = shmContadorLectoresConsecutivos.read();

            if ( nLectoresConsecutivos >= MAX_LECTORES_CONSECUTIVOS )
            {
                CPrinter::printOut( "Se permite el ingreso de nuevos"
                        " lectores" );

                semEntrada.v();
            }

            shmContadorLectoresConsecutivos.write( 0 );
        }

        mutexContadorLectores.v();

    }

    return 0;
}
